package com.gjy.core;

import com.gjy.Level;
import com.gjy.Logger;
import com.gjy.use.DataBase;
import com.gjy.util.DateUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.time.LocalDateTime;

/**
 * CREATE TABLE IF NOT EXISTS logger(
 * `id` BIGINT PRIMARY KEY ,
 * `date_time` DATETIME NOT NULL ,
 * `thread` VARCHAR(255) NOT NULL ,
 * `level` ENUM('INFO','DEBUG','WARN','ERROR') NOT NULL ,
 * `class_name` VARCHAR(255) NOT NULL ,
 * `method_name` VARCHAR(255) NOT NULL ,
 * `message` VARCHAR(255) NOT NULL,
 * `throwable` VARCHAR(255)
 * );
 * 使用 FieldTrans 中的方法，对数据库和POJO类字段进行转换
 *
 * @author 宫静雨
 * @version 1.0
 * @see com.gjy.util.FieldTrans
 * @see com.gjy.use.DataBase
 */
public class DataBaseLogger implements Logger {
    private Class<?> clazz;
    private static final DataBase DB = new DataBase();

    public DataBaseLogger(Class<?> clazz) {
        this.clazz = clazz;
    }

    private void insert(String message, Level level, Throwable... t) {
        Connection connection = DB.getConnection();
        String sql = "INSERT INTO logger(`id`,`date_time`,`thread`,`level`,`class_name`,`method_name`,`message`,`throwable`)" +
                "  VALUES (?,?,?,?,?,?,?,?)";
        try {
            PreparedStatement ps = connection.prepareStatement(sql);
            ps.setLong(1, DateUtil.nanoTime());
            ps.setObject(2, LocalDateTime.now());
            ps.setString(3, Thread.currentThread().getName());
            ps.setString(4, level.name());
            ps.setString(5, clazz.getName());
            ps.setString(6, Thread.currentThread().getStackTrace()[3].getMethodName());
            ps.setString(7, message);
            if (t.length > 0) {
                ps.setString(8, t[0].getMessage());
            }
            ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void info(String message) {
        insert(message, Level.INFO);
    }

    @Override
    public void info(String format, Object... arg) {
        StringBuilder sb = new StringBuilder(format);
        for (Object o : arg) {
            sb.replace(sb.indexOf("{"), sb.indexOf("}") + 1, o.toString());
        }
        insert(sb.toString(), Level.INFO);
    }

    @Override
    public void info(String message, Throwable t) {
        insert(message, Level.INFO, t);
    }

    @Override
    public void debug(String message) {
        insert(message, Level.DEBUG);
    }

    @Override
    public void debug(String format, Object... arg) {
        StringBuilder sb = new StringBuilder(format);
        for (Object o : arg) {
            sb.replace(sb.indexOf("{"), sb.indexOf("}") + 1, o.toString());
        }
        insert(sb.toString(), Level.DEBUG);
    }

    @Override
    public void debug(String message, Throwable t) {
        insert(message, Level.DEBUG, t);
    }

    @Override
    public void warn(String message) {
        insert(message, Level.WARN);
    }

    @Override
    public void warn(String format, Object... arg) {
        StringBuilder sb = new StringBuilder(format);
        for (Object o : arg) {
            sb.replace(sb.indexOf("{"), sb.indexOf("}") + 1, o.toString());
        }
        insert(sb.toString(), Level.WARN);
    }

    @Override
    public void warn(String message, Throwable t) {
        insert(message, Level.WARN, t);
    }

    @Override
    public void error(String message) {
        insert(message, Level.ERROR);
    }

    @Override
    public void error(String format, Object... arg) {
        StringBuilder sb = new StringBuilder(format);
        for (Object o : arg) {
            sb.replace(sb.indexOf("{"), sb.indexOf("}") + 1, o.toString());
        }
        insert(sb.toString(), Level.ERROR);
    }

    @Override
    public void error(String message, Throwable t) {
        insert(message, Level.ERROR, t);
    }
}
